<?php
class xLog {
	private static $target;
	private static $disabled;
	private static $format;
	private static $cfg;
	private static $session = false;
	private static $fname = '';
	private static $logName;
	private static $oTarget;
	
	public static function target($logName, $format = false) {
		self::$logName = $logName;
		self::$cfg = new xConfig ( 'log' );
		if (! (self::$cfg->log_write_errors || self::$cfg->log_write_warnings || self::$cfg->log_write_logs))
			return;
		self::$format = ($format) ? $format : self::$cfg->log_format;
		if (self::$target) {
			fclose ( self::$target );
		}
		$fname = self::$cfg->log_directory . '/' . $logName;
		self::$fname = $logName;
		if ((@filesize ( $fname ) / 1024 > self::$cfg->log_max_size))
			unlink ( $fname );
		if (self::$disabled = self::$cfg->log_disabled)
			return;
		self::$target = fopen ( $fname, "a" );
		if (self::$target === false)
			throw new Exception ( "Unable to open logfile: $logName" );
	}
	
	private static function retarget($target = false) {
		if ($target) {
			if (self::$oTarget == self::$logName)
				return;
			self::$oTarget = self::$logName;
			self::target ( $target );
		} else {
			if (self::$oTarget)
				self::target ( self::$oTarget );
			self::$oTarget = NULL;
		}
	}
	
	public static function targeted() {
		return self::$target;
	}
	
	public static function fatal($message, $code = 999999) {
		self::retarget ( 'fatal' );
		$msg = $message;
		$message = self::write ( 'ERROR', $message );
		self::retarget ();
		throw new xExceptionXML ( $code, htmlentities ( $msg ) );
	}
	
	public static function put($message, $target = false) {
		self::retarget ( $target );
		$message = self::write ( 'LOG', $message );
		if (self::$cfg->display_logs)
			echo '<br/>' . htmlentities ( $message ) . '<br/>';
		self::retarget ();
	}
	
	public static function warning($message, $target = false) {
		self::retarget ( $target );
		$message = self::write ( 'WARNING', $message );
		if (self::$cfg->display_warnings)
			echo '<br/>' . htmlentities ( $message ) . '<br/>';
		self::retarget ();
	}
	
	private static function write($level, $message) {
		$msg = $message;
		switch ($level) {
			case 'LOG' :
				$p = '>';
				break;
			case 'WARNING' :
				$p = '!';
				break;
			case 'ERROR' :
				$p = 'X';
				break;
		}
		$optName = 'log_write_' . strtolower ( $level ) . 's';
		$message = $p . ' ' . self::format ( $level, $message );
		self::$session .= "<log level='$level' logfile='" . self::$fname . "'>$msg</log>";
		if (! self::$cfg->$optName)
			return $message;
		if (self::$disabled)
			return $message;
		if (! self::$target) {
			self::target ( 'system.log' );
			self::$session .= "<log level='$level' logfile='" . self::$fname . "'>$msg</log>";
			self::fatal ( 'Trying to put message before log opened!' );
		}
		fwrite ( self::$target, $message . "\r\n" );
		return $message;
	}
	
	private function format($level, $message) {
		$logFormat = self::$format;
		
		try {
			throw new Exception ( );
		} catch ( Exception $e ) {
			$cb1 = $e->getTrace ();
			$cb [0] = @$cb1 [3] ['class'] . '::' . $cb1 [1] ['function'];
			$cb [1] = @$cb1 [2] ['file'];
			$cb [2] = @$cb1 [2] ['line'];
		}
		
		$logFormat = str_replace ( '__LEVEL__', $level, $logFormat );
		$logFormat = str_replace ( '__FUNCTION__', $cb [0], $logFormat );
		$logFormat = str_replace ( '__FILE__', $cb [1], $logFormat );
		$logFormat = str_replace ( '__LINE__', $cb [2], $logFormat );
		$logFormat = str_replace ( '__DATE__', date ( self::$cfg->date_format ), $logFormat );
		$logFormat = str_replace ( '__TIME__', date ( self::$cfg->time_format ), $logFormat );
		$message = str_replace ( '__MESSAGE__', $message, $logFormat );
		
		return $message;
	}
	
	public static function close() {
		if (self::$disabled)
			return;
		try {
			fclose ( self::$target );
			self::$target = false;
		} catch ( Exception $e ) {
		}
	}
	
	public static function get_session() {
		return '<logs>' . self::$session . '</logs>';
	}
	
	public static function setErrorLevel($lvl) {
		if ($lvl >  0) ini_set('display_errors', 'true');
		else ini_set('display_errors', 'false');
		error_reporting($lvl);
	}

        public static function fatal404() {
            header ( 'Content-type: text/html; charset=utf-8' );
            self::write('ERROR', 'Page not found!');
            $resp = new NotFoundResponse();
            die($resp->out());
        }
}
?>